package com.sec.android.app.myfiles.feature.optimizestorage;

import android.content.Context;
import android.database.Cursor;
import android.mtp.MtpConstants;
import android.provider.MediaStore;

import com.sec.android.app.myfiles.feature.OptimizeStorageMgr.AnalysisResult;
import com.sec.android.app.myfiles.feature.OptimizeStorageMgr.StorageDbType;
import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.info.AppFeatures;
import com.sec.android.app.myfiles.info.FileType;
import com.sec.android.app.myfiles.info.MediaFile;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.FileRecord.OptimizeStorageType;
import com.sec.android.app.myfiles.util.FileUtils;
import com.sec.android.app.myfiles.util.PreferenceUtils;

import java.util.Calendar;
import java.util.List;

/**
 * Created by daesu83.kim on 2016-11-18.
 */

public class MediaProviderFinder implements FileFinder {

    private Context mContext;
    private OptimizeStorageType mType;

    public MediaProviderFinder(Context context, OptimizeStorageType type) {
        mContext = context;
        mType = type;
    }

    @Override
    public void find(List<AnalysisResult> results) {
        Log.d(this, "start find - " + mType.toString());
        long start = System.currentTimeMillis();
        if (results != null) {
            Cursor c = mContext.getContentResolver().query(FileUtils.MEDIA_PROVIDER_URI,
                    null, getSelection(mType), getSelectionArgs(mType), null);
            if (c != null) {
                AnalysisResult result = new AnalysisResult();
                result.mType = mType;
                result.mStorageDbType = StorageDbType.MEDIA_PROVIDER;
                result.mCursor = c;
                results.add(result);
            }
        }
        Log.d(this, "finish find - " + mType.toString() + ", elapsed time=" +
                (System.currentTimeMillis() - start));
    }

    private String getSelection(OptimizeStorageType type) {
        StringBuilder selection = new StringBuilder();
        selection.append("(").append("format").append("!=").append(MtpConstants.FORMAT_ASSOCIATION).append(")");
        switch (type) {
            case LargeFiles:
                selection.append(" AND (").append(MediaStore.Files.FileColumns.SIZE).append(">?)");
                break;
            case UnusedFiles:
                selection.append(" AND (").append(MediaStore.Files.FileColumns.MEDIA_TYPE).append(" IN (")
                        .append(MediaStore.Files.FileColumns.MEDIA_TYPE_IMAGE).append(",")
                        .append(MediaStore.Files.FileColumns.MEDIA_TYPE_AUDIO).append(",")
                        .append(MediaStore.Files.FileColumns.MEDIA_TYPE_VIDEO)
                        .append(")");
                if (AppFeatures.isSupportDocumentType(mContext)) {
                    selection.append(" OR is_doc=1)");
                } else {
                    selection.append(" OR ").append(getDocumentSelection()).append(")");
                }
                if (AppFeatures.isSupportDataAccessed(mContext)) {
                    selection.append(" AND (").append(MediaStore.Files.FileColumns.DATE_MODIFIED).append(" < ? AND (")
                            .append(AppConstants.MEDIA_STORE_FILE_COLUMNS_DATE_ACCESSED).append(" IS NULL OR ")
                            .append(AppConstants.MEDIA_STORE_FILE_COLUMNS_DATE_ACCESSED).append(" < ?))");
                } else {
                    selection.append(" AND (").append(MediaStore.Files.FileColumns.DATE_MODIFIED).append(" < ?)");
                }
                selection.append(" AND (").append(MediaStore.Files.FileColumns.DATA)
                        .append(" IS NOT '").append(OVER_THE_HORIZON_PATH).append("')");
                break;
            case UnnecessaryData:
                selection.append(" AND (").append(MediaStore.Files.FileColumns.SIZE)
                        .append(ETC_FILE_EXTENSION.length > 0 ? "=0 OR " : "=0)");
                for (int i = 0; i < ETC_FILE_EXTENSION.length; i++) {
                    if (i != ETC_FILE_EXTENSION.length - 1) {
                        selection.append(MediaStore.Files.FileColumns.DATA).append(" LIKE ? OR ");
                    } else {
                        selection.append(MediaStore.Files.FileColumns.DATA).append(" LIKE ?)");
                    }
                }
                selection.append(" AND (").append(MediaStore.Files.FileColumns.DATA).append(" NOT LIKE ?)");
                break;
        }
        selection.append(" AND (").append(MediaStore.Files.FileColumns.DATA).append(" LIKE '/storage/emulated%')");
        return selection.toString();
    }

    private static String getDocumentSelection() {
        String[] whereArgs = MediaFile.getDocumentExtensions();
        int length = whereArgs.length;
        for (int i = 0; i < length; i++) {
            whereArgs[i] = "'%." + whereArgs[i] + "'";
        }

        StringBuilder sb = new StringBuilder();
        sb.append('(');
        for (int i = 0; i < length; i++) {
            if (i < length - 1) {
                sb.append(MediaStore.Files.FileColumns.DATA).append(" LIKE ").append(whereArgs[i]).append(" OR ");
            } else {
                sb.append(MediaStore.Files.FileColumns.DATA).append(" LIKE ").append(whereArgs[i]);
            }
        }
        sb.append(')').append(" AND format != ").append(FileType.FOLDER);
        return sb.toString();
    }

    private String[] getSelectionArgs(OptimizeStorageType type) {
        String[] args = {};
        switch (type) {
            case LargeFiles:
                long size = PreferenceUtils.getLargeFilesSize(mContext);
                args = new String[]{String.valueOf(size)};
                break;
            case UnusedFiles:
                Calendar cal = Calendar.getInstance();
                cal.add(Calendar.MONTH, -PreferenceUtils.getUnusedFilesPeriod(mContext));
                String unusedTime = String.valueOf(cal.getTimeInMillis() / 1000);
                if (AppFeatures.isSupportDataAccessed(mContext)) {
                    args = new String[]{unusedTime, unusedTime};
                } else {
                    args = new String[]{unusedTime};
                }
                break;
            case UnnecessaryData:
                args = new String[ETC_FILE_EXTENSION.length + 1];
                for (int i = 0; i < ETC_FILE_EXTENSION.length; i++) {
                    args[i] = '%' + ETC_FILE_EXTENSION[i];
                }
                args[ETC_FILE_EXTENSION.length] = "%/.nomedia";
                break;
        }
        return args;
    }
}
